//var common = require('common');
//common.http.createServer(common.router).listen(3030,'127.0.0.1');
var fs = require('fs');
var querystring = require('querystring');
var http = require('http');
var url = require('url');
var formiable = require('formidable');
/**
 * 序列化cookie
 */
var serialize = function(name,val,opt){
	var pairs = [name + '=' + val];
	opt = opt || {};
	
	if(opt.maxAge) pairs.push('Max-Age='+opt.maxAge);
	if(opt.domain) pairs.push('Max-Age='+opt.domain);
	if(opt.path) pairs.push('Max-Age='+opt.path);
	if(opt.expires) pairs.push('Max-Age='+opt.expires);
	if(opt.httpOnly) pairs.push('Max-Age='+opt.httpOnly);
	if(opt.secure) pairs.push('Max-Age='+opt.secure);
	
	return pairs.join('; ');
}

/**
 * 解析json
 */
var parseJSON = function(req, callback){
	try{
		req.body = JSON.parse(req.rawBody);
		callback();
	}catch(e){
		//TODO 错误日志
//		res.writeHead(400);
//		res.end('Invalid JSON');
		return;
	}
}

/**
 * 解析字符串
 */
var parseString = function(req, callback){
	try{
		req.body = querystring.parse(req.rawBody);
		callback();
	}catch(e){
		//TODO 错误日志
//		res.writeHead(400);
//		res.end('Invalid JSON');
		return;
	}
}

/**
 * 解析上传文件
 */
var parseMultipart = function(req, callback){
	var form = new formiable.IncomingForm();
	form.parse(req, function(err, fields, files){
		req.body = fields;
		req.files = files;
		callback();
	});
}


var hasBody = function(req){
	return 'transfer-encoding' in req.headers || 'content-length' in req.headers;
}

var mime = function(req){
	var str = req.headers['content-type'] || '';
	return str.split(';')[0];
}

/**
 * 提取body的值
 * 
 */
var parseBody = function(req,callback){
	if(hasBody(req)){
		if(mime(req) == 'application/json'){
			//解析 json 数据
			parseJSON(req, callback);
		} else if(mime(req) == 'aplication/xml'){
			//TODO::解析 xml 数据
		} else if(req.headers['content-type'] == 'application/x-www-form-urlencoded'){
			parseString(req, callback);
		} else {
			req.body = '';
			callback();
		}
	} else {
		callback();
	}
}
/**
 * 处理请求
 * @param req
 * @param res
 */

function router(req, res){
	//hack cookie 为了session
	var writeHead = res.writeHead;
	res.writeHead = function() {
		if(req.session && req.session.id){
			var cookies = res.getHeader('Set-Cookie');
			var session = serialize('session_id', req.session.id);
			cookies = Array.isArray(cookies) ? cookies.concat(session) : [cookies, session];
			res.setHeader('Set-Cookie', cookies);
		}
		return writeHead.apply(this, arguments);
	}

	var pathname = url.parse(req.url).pathname;
	var query = querystring.parse(url.parse(req.url).query);
	var paths = pathname.split('/');
	var route = paths[1] || 'd';
	var controller = paths[2] || 'home';
	var action = paths[3] || 'index';
	

	//不符合路由规则的死掉
	if(!~'d res'.indexOf(route)){
		res.writeHead(500);
		res.end();
		return;
	}

	if(route == 'res'){
		fs.readFile('\.\/res\/'+controller+'\/'+action,function(err, data){
			if(err){
				res.writeHead(500);
				res.end();
				return;
			}
			
			//设置缓存
			var expires = new Date();
			expires.setTime(expires.getTime() + 3600 * 24 * 7);
			res.setHeader('Expires',expires.toUTCString());
			res.setHeader('Cache-Control',"max-age=" + 3600 * 24 * 7);
			res.writeHead(200);
			res.end(data);
		});
		return;
	}
	
	var globals = {
			req		: req,
			res		: res,
			query	: query,
	}

	//获取body
	if(hasBody(req)){
		if(req.headers['content-type'] == 'application/x-www-form-urlencoded' || mime(req) == 'application/json'){
			var buffers = [];
			req.on('data', function(chunk){
				buffers.push(chunk);
			});
			req.on('end', function(){
				req.rawBody = Buffer.concat(buffers).toString();
				parseBody(req, handle);
			});
		} else if(mime(req) == 'multipart/form-data'){
			//解析文件
			parseMultipart(req, handle);
		}
	}else{
		handle();
	}

	var handle = function(){
		if(route == 'd'){
			var module = require('\.\/controllers\/'+controller);
		}

		if(module[action]){
			module[action](function(html){
				res.writeHead(200);
				res.end(html);
			},globals);
		}else{
			res.writeHead(500);
			res.end();
		}
	}
}

http.createServer(router).listen(3030,'127.0.0.1');